/* Copyright (c) 2004-2008, Andriy Nikolov
 * All rights reserved.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package org.processmining.email;

import java.awt.*;
import java.util.*;

/**
 * <p>The panel, which draws in itself the case-person diagram in the standalone version </p>
 *
 * @author Andriy Nikolov
 * @version 1.0
 */
public class CasePersonTablePanel
    extends DiagramPanel {

  CasePersonTable table;
  Hashtable caseNodesTable, personNodesTable;
  Vector caseNodes, personNodes;

  public CasePersonTablePanel() {
    super();
    caseNodes = new Vector();
    personNodes = new Vector();
    caseNodesTable = new Hashtable();
    personNodesTable = new Hashtable();
  }

  public void setTable(CasePersonTable table) {
    this.table = table;
    createNodes();
    createArcs();
  }

  public CasePersonTable getTable() {
    return table;
  }

  public void calculateSize() {
    int height;
    Dimension size;
    maxNumberOfNodes = Math.max(caseNodes.size(), personNodes.size());

    height = DIAGRAM_TOPMOST_POINT*scale;
    height+=(DiagramNode.NODE_HEIGHT+DiagramNode.NODE_MIN_INTERVAL)*scale*maxNumberOfNodes;
    size = new Dimension(this.getWidth(), height);
    setSize(size);
    setPreferredSize(size);
    setMinimumSize(size);
  }

  private void createNodes() {
      Vector caseList, personList;
      PersonNode curPersonNode;
      CaseNode curCaseNode;
      String curName;
      int i;

      caseList = table.getCaseList();
      for(i=0;i<caseList.size();i++) {
        curName = (String)caseList.get(i);
        curCaseNode = new CaseNode(curName, this);
        caseNodesTable.put(curName, curCaseNode);
        caseNodes.add(curCaseNode);
      }

      personList = table.getPersonList();
      for(i=0;i<personList.size();i++) {
        curName = (String)personList.get(i);
        if(table.isPersonConnected(curName)) {
          curPersonNode = new PersonNode(curName, this);
          personNodesTable.put(curName, curPersonNode);
          personNodes.add(curPersonNode);
        }
      }

      calculateSize();
      DiagramNode curNode;
      Point nodeCenter;

      for(i=0;i<caseNodes.size();i++) {
        curNode = (DiagramNode)caseNodes.get(i);
        nodeCenter = calculateNodeCenter(i, caseNodes.size(), true);
        curNode.setCenter(nodeCenter);
        add(curNode, null);
      }

      for(i=0;i<personNodes.size();i++) {
        curNode = (DiagramNode)personNodes.get(i);
        nodeCenter = calculateNodeCenter(i, personNodes.size(), false);
        curNode.setCenter(nodeCenter);
        add(curNode, null);
      }
  }

  private Point calculateNodeCenter(int cur, int total, boolean isCase) {
    double cx, cy;
    double interval;
    if(isCase) {
      cx = this.getWidth()/4;
    } else {
      cx = 3*this.getWidth()/4;
    }
    interval = (DiagramNode.NODE_HEIGHT+DiagramNode.NODE_MIN_INTERVAL)*DiagramNode.scale*(((double)(maxNumberOfNodes))/((double)(total)));
    cy = DIAGRAM_TOPMOST_POINT+cur*interval;
    return new Point(new Double(cx).intValue(), new Double(cy).intValue());
  }

  private void createArcs() {
    double weight;
    DiagramArc curArc;
    int i, j;
    double max;
    arcs.clear();
    DiagramNode caseNode;
    DiagramNode personNode;

    for (j=0;j<personNodes.size();j++) {
      personNode = (DiagramNode)personNodes.get(j);
      max = 0;
      if(showOnlyMaximalArcs) {
        // find the case, to which the person is mostly connected
        for (i=0;i<caseNodes.size();i++) {
          caseNode = (DiagramNode) caseNodes.get(i);
          weight = table.getNormalizedWeight(caseNode.getText(), personNode.getText());
          if(weight>max) {
            max = weight;
          }
        }
      }
      for (i=0;i<caseNodes.size();i++) {
        caseNode = (DiagramNode)caseNodes.get(i);
        weight = table.getNormalizedWeight(caseNode.getText(), personNode.getText());
        if(weight>0) {
          if(showOnlyMaximalArcs) {
            if(weight<max) {
              continue;
            }
          }
          curArc = new DiagramArc();
          curArc.setWeight(weight);
          curArc.setFrom(caseNode);
          curArc.setTo(personNode);
          arcs.add(curArc);
        }
      }
    }
  }
}
